#PCB数据结构定义
class PCB:
    #初始化PCB数据结构
    def __init__(self,PID,CpuTime,AllResource,re_mSize,intoTime=0,name='null',priority=0):
        #内部标识名 (具有唯一性，用数字表示)
        self.PID = PID

        #外部标识名
        self.name = name

        #进程优先级  （使用数字表示，数字越大，优先级越高，默认为0）
        self.priority = priority

        #状态  （有四种，分别为就绪（TASK_READY），运行（TASK_RUNING），阻塞（TASK_BLOCK），初始（TASK_INIT））
        self.task_state = 'TASK_INIT'
        #阻塞的原因 （有四种，分别为
        #       辅存申请失败（aSize_Application_Fail）
        #       主存申请失败（mSize_Application_Fail）
        #       设备申请失败（device_Application_Fail）
        #     信号量申请失败（semaphore_Application_Fail）
        self.BLOCK_CAUSE = ''
        

        #申请任务的类型,有以下几种
        #'D'设备申请
        #'F'文件申请
        #'M'内存申请
        #'R'资源申请
        #'C'CPU申请
        #'S'信号量申请
        # 进程刚创建时,先申请内存(故先初始化为M)
        self.task_application = 'M'

        # 进入内存时间
        self.intoTime = intoTime

        # SJF优先级
        self.Counter = CpuTime

        # 界面显示CPU服务时间(仅用于完成运作后显示pcb数据使用)
        self.OverCpuTime = CpuTime

        #cpu服务时间
        self.CpuTime = CpuTime
        #设备服务时间
        self.DeviceTime = 0
        #资源服务时间
        self.ResourceTime = 0
        #内存最后使用时间
        self.MLastTime = 0

        #完成任务时间
        self.completeTime = 0

        #目前已经占用的内存大小
        self.Now_mSize = 0
        #目前需要(释放)的内存大小
        self.re_mSize = re_mSize;
        #是否需要申请（释放）内存 True表示申请，False表示释放
        self.Mrequest = True;
        #释放所有内存请求（True 释放所有，False 不释放所有）
        self.MAllRelease = False

        #目前需要存储或删除的文件名
        self.FileName = ''
        #目前需要(释放)的文件大小
        self.re_fSize = 0
        #需要存储、删除、获取设备  storage(存储) or delete(删除) or gain(获取)
        self.Frequest= ''
        #文件的类型,文件夹或者文件 0 为文件，1为文件夹
        self.Ftype = 0

        # 需要申请资源的设备名
        self.re_Dname = ''
        # 需要存储、删除、获取设备  storage(存储) or delete(删除) or gain(获取)
        self.Drequest = False
        
        #当资源使用完毕，无需向资源窗口询问，
        #直接将re_Resource=[0,0,0],Now_Resource=[0,0,0]
        #进程需要的资源总数
        self.AllResource = AllResource
        #目前需要的资源的数量
        self.re_Resource = [0,0,0]
        #目前拥有资源的数量
        self.Now_Resource = [0,0,0]
        #是否需要申请（释放）设备  True表示申请，False表示释放(仅用于表示)
        self.Rrequest = False

        #PCB中的同步信号量(字典类型)
        self.Semaphore = {}
        #PCB中,要申请或释放的信号量(列表，其中存储信号量的key)
        self.re_mutex = []
        #是否要申请（释放）信号量 True表示释放，False表示申请
        self.Srequest = False



        #事件    (采用存储多个字典，当完成进程时还需要多少CPU时间时，触发相应的事件，CPU剩余时间片由大到小)
        self.event = []
        ''' [{事件},{事件},{事件},{事件},{事件}]
        设备事件设置模式
        {'CpuTime':CpuTime , 'task_application':'D' , 
            're_Dname':'设备名' , 'DeviceTime':'设备服务时间' , 'Drequest':'True(申请) or False(释放)'}
        资源事件设置模式
        {'CpuTime':cpu运行时间, 'task_application':'R' , 'ResourceTime':'资源处理时间' , 're_Resource':'目前需要的资源的数量' 
            'Rrequest':True(申请) or False(释放)}
        文件事件设置模式
        {'CpuTime':CpuTime, 'task_application':'F', 'Frequest':'storage(存储) or delete(删除) or gain(获取)' ,
            'FileName':'文件名','re_fSize':'文件大小' ,'Ftype':'0为文件 1为文件夹'}
        内存事件设置模式
        {'CpuTime':CpuTime, 'task_application':'M' , 'Mrequest':'True(申请) or False(释放)', 're_mSize':'内存申请(释放)的大小'
         'MAllRelease':'True(释放所有) or False(不释放)'}
        信号量事件设置模式
        {'CpuTime':CpuTime,'task_application':'S', 're_mutex':mutex(存semaphore的key), 'Srequest':'True(申请) or False(释放)'}

        使用事件时，记得第一次步为申请内存空间
        
        '''

    #将现有的所有资源设置为释放状态（不包含信号量）
    def releaseAllResource(self):
        self.Mrequest = False;
        self.re_aSize = self.Now_mSize

        self.Drequest = False
        self.re_Device = self.Now_Device    

        self.Arequest = False
        self.re_aSize = self.Now_aSize
        
    #将所有资源都设置为申请状态（不含信号量）
    def requestAllResourse(self):
        self.Mrequest = True
        self.Drequest = True
        self.Arequest = True

    #限定输入的数据格式
    def __setattr__(self, name, value):
        #判断输入PID是否合法，不合法则默认为-1
        if name == 'PID':
            # isinstance(value,int):判断数据类型
            if isinstance(value,int):
                if value<0:
                    print('PID大小输入错误，请重新修改为大于0的数据')
                    super().__setattr__(name, -1)
                else:
                    super().__setattr__(name, value)
            else:
                print('PID类型输入错误，请重新修改为int型且大于0的数据')
                super().__setattr__(name, -1)
        #判断输入CPU处理时间是否合法，不合法则默认为3000
        if name == 'Counter':
            # isinstance(value,int):判断数据类型
            if isinstance(value,int):
                if value<0:
                    print('CPU时间输入错误，请重新修改为大于0的数据')
                    super().__setattr__(name, 3000)
                else:
                    super().__setattr__(name, value)
            else:
                print('CPU时间类型输入错误，请重新修改为int型且大于0的数据')
                super().__setattr__(name, 3000)
        #判断输入优先级是否合法，不合法则默认为0
        if name == 'priority':
            # isinstance(value,int):判断数据类型
            if isinstance(value,int):
                if value<0:
                    super().__setattr__(name, 0)
                else:
                    super().__setattr__(name, value)
            else:
                print('优先级输入错误，请重新修改为int型且》=0的数据')
                super().__setattr__(name, 0)
        # 判断输入事件是否合法，不合法则默认为0
        if name == 'event':
            if isinstance(value, list):
                super().__setattr__(name, value)
            else:
                print('请按格式输入事件')
                super().__setattr__(name, [])
        if name == 'task_application':
            # 'D'设备申请  #'F'文件申请 #'M'内存申请 #'R'资源申请 #'C'CPU申请 #'S'信号量申请
            if value=='D' or value=='F' or value=='M' or value=='R' or value=='C' or value=='S':
                super().__setattr__(name, value)
            else:
                print('进程状态输入错误,请重新输入')
                super().__setattr__(name, '')
        #判断内存容量输入是否合法，不合法则默认为10
        if name == 're_mSize':
            if isinstance(value,int):
                super().__setattr__(name, value)
            else:
                print('请输入正确的内存空间')
                super().__setattr__(name, 10)     
               
        else:
            super().__setattr__(name, value)

